/*----------------------------------------------- Marlin Toolkit--------------------------------------*
Authors : Daniel Randle, Alex Bourne
Date Created : Feb 25 2013

File:
	mainwindow.cpp

Description:
	This file contains the definition for the MainWindow class functions along with any other
	neccessary functions
*-----------------------------------------------------------------------------------------------------*/


// Includes
#include <mainwindow.h>
#include <mapwindow.h>
#include <objectwindow.h>
#include <mapselectionwindow.h>
#include <markerwindow.h>
#include <shaderwindow.h>
#include <undowindow.h>
#include <shaderbuildwindow.h>
#include <debugwindow.h>
#include <debug.h>
#include <logfile.h>
#include <qfiledialog.h>
#include <toolkit.h>

// Qt Includes
#include <qdockwidget.h>
#include <qmenu.h>
#include <qaction.h>
#include <qtoolbar.h>
#include <qfile.h>
#include <qmenubar.h>
#include <qevent.h>

#include <nsengine.h>



namespace ToolkitGui
{

/*-----------------------*
 |class MainWindow BEGINS|
 *-----------------------*/

/* Constructor
Description:
	Create and initialize all parts of the main window - call the constructor of the parent class QMainWindow
	to utilize it's UI functionality

Parameters:
	None

Return:
	None
*/
MainWindow::MainWindow(Toolkit * tk):
	QMainWindow(),
	toolkit(tk)
{

	_initWindows();
	_initDialogs();
	_initObjects();
	_setupActions();
	_setupMenus();
	_setupToolBars();
	_setupDockWindows();
	_setupUi();
	_setupConnections();
}


/* Destructor
Description:
	All QT objects de-allocate their own memory so not much needs to happen in the destructor here

Parameters:
	None

Return:
	None
*/
MainWindow::~MainWindow()
{}


/*-----------------------------------------PRIVATE FUNCTIONS-------------------------------------------*/


/* _initWindows
Description:
	This function allocates memory for all of the windows needed in the toolkit -
	the windows then have their own setup call to show their UI correctly

Parameters:
	None

Return:
	None
*/
void MainWindow::_initWindows()
{
	QGLFormat qf;
	qf.setProfile(QGLFormat::CoreProfile);

	mapWindow = new MapWindow(qf,this,this);
	objectWindow = new ObjectWindow(this);
	mapSelectionWindow = new MapSelectionWindow(this);
	markerWindow = new MarkerWindow(this);
	shaderWindow = new ShaderWindow(this);
	undoWindow = new UndoWindow(this);
	shaderBuildWindow = new ShaderBuildWindow(this);
	
	#ifdef DEBUG
	debugWindow = new DebugWindow(this);
	#endif
}

/* _initDialogs
Description:
	This function allocates memory for all of the dialogs needed in the toolkit -
	the dialogs then have their own setup call to show their UI correctly

Parameters:
	None

Return:
	None
*/
void MainWindow::_initDialogs()
{
}

/* _initObjects
Description:
	This function allocates memory for all of the objects needed in the GUI portion of toolkit -
	the objects then have their own setup calls to show their UI correctly

Parameters:
	None

Return:
	None
*/
void MainWindow::_initObjects()
{

	// Actions Init
	savePluginA = new QAction("Save plugin",this);
	loadPluginA = new QAction("Load plugin",this);
	toggleShowOccupiedTiles = new QAction(QIcon(":/Toolbars/toggleOccupiedTiles"),"Show Occupied Tiles",this);


	// Toolbar Init
	mainToolBar = new QToolBar(this);

	// Menu init
	fileMenu = new QMenu(tr("&File"), this);
	editMenu = new QMenu(tr("&Edit"), this);
	viewMenu = new QMenu(tr("&View"), this);

	// Init Dock Windows
	mapDock = new QDockWidget("Map Editor",this);
	mapSelectionDock = new QDockWidget("Map Selection",this);
	objectDock = new QDockWidget("Objects",this);
	markerDock = new QDockWidget("Markers",this);
	shaderDock = new QDockWidget("Shaders",this);
	undoDock = new QDockWidget("Undo Commands",this);
	shaderBuildDock = new QDockWidget("Shader Build",this);

	#ifdef DEBUG
	d = NULL;
	debugDock = new QDockWidget("Debug", this);
	#endif
}


/* _setupActions
Description:
	Sets up all of the actions in the toolkit in the main menus and toolbars - I like to store the 
	actions for easy signal slot connection

Parameters:
	None

Return:
	None
*/
void MainWindow::_setupActions()
{
	toggleShowOccupiedTiles->setCheckable(true);
}


/* _setupMenus
Description:
	Sets up all of the menus in the toolkit that appear on the top of the main window and adds actions/submenus

Parameters:
	None

Return:
	None
*/
void MainWindow::_setupMenus()
{
	// Adding actions to menus
	fileMenu->addAction(savePluginA);
	fileMenu->addAction(loadPluginA);
	// Adding menus to MainWindow menu bar
	menuBar()->addMenu(fileMenu);
	menuBar()->addMenu(editMenu);
	menuBar()->addMenu(viewMenu);
}


/* _setupToolBars
Description:
	Sets up the main window toolbars and adds the neccessary actions

Parameters:
	None

Return:
	None
*/
void MainWindow::_setupToolBars()
{
	mainToolBar->addAction(toggleShowOccupiedTiles);
	// Add toolbars to main window
	addToolBar(mainToolBar);
}


/* _setupDockWindows
Description:
	Sets up the dock windows that are shown in the Main Window area

Parameters:
	None

Return:
	None
*/
void MainWindow::_setupDockWindows()
{

	// Setup window docks
	mapDock->setWidget(mapWindow);
	objectDock->setWidget(objectWindow);
	mapSelectionDock->setWidget(mapSelectionWindow);
	markerDock->setWidget(markerWindow);
	shaderDock->setWidget(shaderWindow);
	undoDock->setWidget(undoWindow);
	shaderBuildDock->setWidget(shaderBuildWindow);

	// Add dock widgets to main window
	addDockWidget(Qt::RightDockWidgetArea, mapDock);
	addDockWidget(Qt::LeftDockWidgetArea, mapSelectionDock);
	addDockWidget(Qt::LeftDockWidgetArea, objectDock);
	addDockWidget(Qt::LeftDockWidgetArea, markerDock);
	addDockWidget(Qt::LeftDockWidgetArea, shaderDock);
	addDockWidget(Qt::LeftDockWidgetArea, undoDock);
	addDockWidget(Qt::RightDockWidgetArea, shaderBuildDock);

	// set up debug dockwindow
	#ifdef DEBUG
	debugDock->setWidget(debugWindow);
	addDockWidget(Qt::RightDockWidgetArea,debugDock);
	tabifyDockWidget(debugDock,shaderBuildDock);
	debugDock->raise();
	#endif

	tabifyDockWidget(mapSelectionDock,objectDock);
	tabifyDockWidget(objectDock,markerDock);
	tabifyDockWidget(markerDock,shaderDock);
	mapSelectionDock->raise();

	setTabPosition(Qt::AllDockWidgetAreas, QTabWidget::North);
}

/* _setupUi
Description:
	Sets up the Ui for the main window

Parameters:
	None

Return:
	None
*/
void MainWindow::_setupUi()
{

	mapWindow->setMinimumSize(size() / 1.5);
	mapWindow->setMaximumSize(size() / 1.2);
	//mapWindow->setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum));

	showMaximized();
}


/* _setupConnections
Description:
	Sets up the connections between actions/buttons and the functions that will do things when they are 
	clicked or toggled

Parameters:
	None

Return:
	None
*/
void MainWindow::_setupConnections()
{
	connect(savePluginA,SIGNAL(triggered()),this, SLOT(onSavePlugin()));
	connect(loadPluginA,SIGNAL(triggered()),this, SLOT(onLoadPlugin()));
	connect(objectWindow, SIGNAL(activateBuild()), mapWindow, SLOT(onActivateBuild()));
	connect(toggleShowOccupiedTiles, SIGNAL(toggled(bool)), this, SLOT(onToggleOccupiedTiles(bool)));
}

void MainWindow::resizeEvent( QResizeEvent * event )
{
	mapWindow->setMinimumSize(size() / 1.6);
	mapWindow->setMaximumSize(size() / 1.2);
	QWidget::resizeEvent(event);
}


/*------------------------------------------- PRIVATE SLOTS -------------------------------------------*/

void MainWindow::onSavePlugin()
{
	d->print("saving...");
	QString fName = QFileDialog::getSaveFileName(this, "Save plugin map file","Maps","*.bbm");
	if (fName == QString())
		return;
	toolkit->savePluginToFile(fName);
}

void MainWindow::onLoadPlugin()
{
	d->print("loading...");
	QString fName = QFileDialog::getOpenFileName(this, "Load plugin map file","Maps","*.bbm");
	if (fName == QString())
		return;
	toolkit->loadPluginFromFile(fName);
}

void MainWindow::onToggleOccupiedTiles(bool checked)
{
	engine->setShowOccupiedTiles(checked);
}

void MainWindow::setEngine(NSEngine * eng)
{
	engine = eng;
	objectWindow->setEngine(engine);
}

MapWindow * MainWindow::getMapWindow()
{
	return mapWindow;
}

ObjectWindow * MainWindow::getObjectWindow()
{
	return objectWindow;
}

MapSelectionWindow * MainWindow::getMapSelectionWindow()
{
	return mapSelectionWindow;
}

MarkerWindow * MainWindow::getMarkerWindow()
{
	return markerWindow;
}

ShaderWindow * MainWindow::getShaderWindow()
{
	return shaderWindow;
}

void MainWindow::myUpdate()
{
	objectWindow->update();
}

#ifdef DEBUG
void MainWindow::setDebug(Debug * debug)
{
	d = debug;
	d->setDebugWindow(debugWindow);

	// Set up sub windows with debug abilites
	mapWindow->setDebug(d);
}
#endif


/*--------------------*
 | class MainWindow ENDS |
 *--------------------*/

}